﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

namespace HdipCricketClub.Models
{
    [MetadataType(typeof(OpponentFixturePlayerMetaData))]
    public partial class OpponentFixturePlayer
    {
        CricketClubEntities db = new CricketClubEntities();


        public List<OpponentFixturePlayer> ParseFormCollectionForOpponentPlayersBattedSecond(FormCollection formCollection, Fixture fixture)
        {
            string[] fixtureId = formCollection.GetValues("item.op_fixture_id");
            string[] batsmanNumber = formCollection.GetValues("item.op_batsman_number");
            string[] playerName = formCollection.GetValues("item.op_player_name");
            string[] bowlerNumber = formCollection.GetValues("item.op_bowler_number");

            List<OpponentFixturePlayer> opponentPlayers = new List<OpponentFixturePlayer>();

            for (int i = 0; i < fixture.no_of_players; i++)
            {
                OpponentFixturePlayer player = new OpponentFixturePlayer()
                                             {
                                                 op_fixture_id = Int32.Parse(fixtureId[i]),
                                                 op_batsman_number = Int32.Parse(batsmanNumber[i]),
                                                 op_player_name = playerName[i]
                                             };
                if (bowlerNumber[i] != "")
                {
                    player.op_bowler_number = Int32.Parse(bowlerNumber[i]);
                }

                opponentPlayers.Add(player);
            }
            return opponentPlayers;
        }

        public List<OpponentFixturePlayer> GetOpponentBowlers(List<OpponentFixturePlayer> players)
        {
            List<OpponentFixturePlayer> opponentBowlers = new List<OpponentFixturePlayer>();

            foreach (OpponentFixturePlayer player in players)
            {
                if (player.op_bowler_number != null)
                {
                    opponentBowlers.Add(player);
                }
            }

            List<OpponentFixturePlayer> sortedOpponentBowlers = opponentBowlers.OrderBy(ob => ob.op_bowler_number).ToList();

            return sortedOpponentBowlers;
        }

        public List<string> ValidateOpponentBatsmen(List<OpponentFixturePlayer> opponentBatsmen, Fixture fixture)
        {
            string message;

            List<string> errorMessages = new List<string>();

            List<int> batsmenNumbers = new List<int>();

            foreach (OpponentFixturePlayer batsman in opponentBatsmen)
            {
                batsmenNumbers.Add(batsman.op_batsman_number);
            }

            batsmenNumbers.Sort();

            if (batsmenNumbers.First() != 1)
            {
                message = "The first batsman number must be 1";
                errorMessages.Add(message);
            }

            if (batsmenNumbers.Last() != fixture.no_of_players)
            {
                message = "The last batsman number must equal the number of players";
                errorMessages.Add(message);
            }

            List<int> uniqueBatsmenNumbers = new List<int>();
            List<int> duplicateBatsmenNumbers = new List<int>();

            foreach (OpponentFixturePlayer batsman in opponentBatsmen)
            {
                if (uniqueBatsmenNumbers.Contains(batsman.op_batsman_number))
                {
                    duplicateBatsmenNumbers.Add(batsman.op_batsman_number);
                }
                else
                {
                    uniqueBatsmenNumbers.Add(batsman.op_batsman_number);
                }
            }

            foreach (OpponentFixturePlayer batsman in opponentBatsmen)
            {
                if (duplicateBatsmenNumbers.Contains(batsman.op_batsman_number))
                {
                    message = "Batsman number " + batsman.op_batsman_number + " duplicated, " + batsman.op_player_name;
                    errorMessages.Add(message);
                }
            }

            List<string> uniqueBatsmenNames = new List<string>();
            List<string> duplicateBatsmenNames = new List<string>();

            foreach (OpponentFixturePlayer batsman in opponentBatsmen)
            {
                if (batsman.op_player_name == null)
                {
                    message = "No player name entered, batsman number " + batsman.op_batsman_number;
                    errorMessages.Add(message);
                }
                else
                {
                    if (uniqueBatsmenNames.Contains(batsman.op_player_name))
                    {
                        duplicateBatsmenNames.Add(batsman.op_player_name);
                    }
                    else
                    {
                        uniqueBatsmenNames.Add(batsman.op_player_name);
                    }
                }
            }

            foreach (OpponentFixturePlayer batsman in opponentBatsmen)
            {
                if (duplicateBatsmenNames.Contains(batsman.op_player_name))
                {
                    message = "Batsman name " + batsman.op_player_name + " duplicated,";
                    errorMessages.Add(message);
                }
            }
            return errorMessages;
        }

        public List<string> ValidateOpponentBowlers(List<OpponentFixturePlayer> opponentBowlers)
        {
            string message;

            List<string> errorMessages = new List<string>();

            List<int> bowlerNumbers = new List<int>();

            foreach (OpponentFixturePlayer bowler in opponentBowlers)
            {
                if (bowler.op_bowler_number != null)
                {
                    bowlerNumbers.Add((int)bowler.op_bowler_number);
                }
            }

            if (bowlerNumbers.Count() == 0)
            {
                message = "No bowler numbers entered";
                errorMessages.Add(message);
            }

            else
            {
                bowlerNumbers.Sort();

                if (bowlerNumbers.First() != 1)
                {
                    message = "The first bowler number must be 1";
                    errorMessages.Add(message);
                }
                if (bowlerNumbers.Last() != bowlerNumbers.Count())
                {
                    message = "The final bowler number must be equal to the number of bowlers";
                    errorMessages.Add(message);
                }

                List<int> uniqueBowlerNumbers = new List<int>();
                List<int> duplicateBowlerNumbers = new List<int>();

                foreach (OpponentFixturePlayer bowler in opponentBowlers)
                {
                    if (uniqueBowlerNumbers.Contains((int)bowler.op_bowler_number))
                    {
                        duplicateBowlerNumbers.Add((int)bowler.op_bowler_number);
                    }
                    else
                    {
                        uniqueBowlerNumbers.Add((int)bowler.op_bowler_number);
                    }
                }

                foreach (OpponentFixturePlayer bowler in opponentBowlers)
                {
                    if (duplicateBowlerNumbers.Contains((int)bowler.op_bowler_number))
                    {
                        message = "Bowler number " + bowler.op_bowler_number + "duplicated, " + bowler.op_player_name;
                        errorMessages.Add(message);
                    }
                }
            }
            return errorMessages;
        }

        public List<string> ValidateOpponentBatsmenScores(List<OpponentFixturePlayer> opponentBatsmen)
        {
            string message;

            List<string> errorMessages = new List<string>();

            foreach (OpponentFixturePlayer batsman in opponentBatsmen)
            {
                if (batsman.op_how_out == null)
                {
                    message = batsman.op_player_name + " how out must be entered";
                    errorMessages.Add(message);
                }

                if (batsman.op_how_out == 1)
                {
                    if (batsman.op_fielder_name != null)
                    {
                        message = batsman.op_player_name + " if dismissal type is bowled no fielder name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_bowler_name == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is bowled a bowler name must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is bowled a value for runs must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs < 0)
                    {
                        message = batsman.op_player_name + " if dismissal type is bowled a value for runs cannot be less than 0";
                        errorMessages.Add(message);
                    }
                }

                if (batsman.op_how_out == 2)
                {
                    if (batsman.op_fielder_name != null)
                    {
                        message = batsman.op_player_name + "if dismissal type is lbw no fielder name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_bowler_name == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is lbw a bowler name must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is lbw a value for runs must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs < 0)
                    {
                        message = batsman.op_player_name + " if dismissal type is lbw a value for runs cannot be less than 0";
                        errorMessages.Add(message);
                    }
                }

                if (batsman.op_how_out == 3)
                {
                    if (batsman.op_fielder_name == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is caught a fielder name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_bowler_name == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is caught a bowler name must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is caught a value for runs must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs < 0)
                    {
                        message = batsman.op_player_name + " if dismissal type is caught a value for runs cannot be less than 0";
                        errorMessages.Add(message);
                    }
                }

                if (batsman.op_how_out == 4)
                {
                    if (batsman.op_fielder_name == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is stumped a fielder name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_bowler_name == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is stumped a bowler name must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is stumped a value for runs must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs < 0)
                    {
                        message = batsman.op_player_name + " if dismissal type is stumped a value for runs cannot be less than 0";
                        errorMessages.Add(message);
                    }
                }

                if (batsman.op_how_out == 5)
                {
                    if (batsman.op_fielder_name != null)
                    {
                        message = batsman.op_player_name + " if dismissal type is hit wicket no fielder name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_bowler_name == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is hit wicket a bowler name must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is hit wicket a value for runs must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs < 0)
                    {
                        message = batsman.op_player_name + " if dismissal type is hit wicket a value for runs cannot be less than 0";
                        errorMessages.Add(message);
                    }
                }

                if (batsman.op_how_out == 6)
                {
                    if (batsman.op_fielder_name != null)
                    {
                        message = batsman.op_player_name + "if dismissal type is run out no fielder name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_bowler_name != null)
                    {
                        message = batsman.op_player_name + " if dismissal type is run out no bowler name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is run out a value for runs must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs < 0)
                    {
                        message = batsman.op_player_name + " if dismissal type is run out a value for runs cannot be less than 0";
                        errorMessages.Add(message);
                    }
                }
                if (batsman.op_how_out == 7)
                {
                    if (batsman.op_fielder_name != null)
                    {
                        message = batsman.op_player_name + " if dismissal type is obstructed field no fielder name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_bowler_name == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is obstructed field a bowler name must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is obstructed field a value for runs must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs < 0)
                    {
                        message = batsman.op_player_name + " if dismissal type is obstructed field a value for runs cannot be less than 0";
                        errorMessages.Add(message);
                    }
                }

                if (batsman.op_how_out == 8)
                {
                    if (batsman.op_fielder_name != null)
                    {
                        message = batsman.op_player_name + "if dismissal type is did not bat no fielder name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_bowler_name != null)
                    {
                        message = batsman.Member.InitialAndLastName + " if dismissal type is did not bat no bowler name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs != null)
                    {
                        message = batsman.op_player_name + " if dismissal type is did not bat no value for runs must be entered";
                        errorMessages.Add(message);
                    }
                }

                if (batsman.op_how_out == 9)
                {
                    if (batsman.op_fielder_name != null)
                    {
                        message = batsman.op_player_name + "if dismissal type is not out no fielder name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_bowler_name != null)
                    {
                        message = batsman.op_player_name + " if dismissal type is not out no bowler name should be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs == null)
                    {
                        message = batsman.op_player_name + " if dismissal type is not out a value for runs must be entered";
                        errorMessages.Add(message);
                    }
                    if (batsman.op_batting_runs < 0)
                    {
                        message = batsman.op_player_name + " if dismissal type is not out a value for runs cannot be less than 0";
                        errorMessages.Add(message);
                    }
                }
            }
            return errorMessages;
        }

        public List<string> ValidateOpponentBowlersScores(List<OpponentFixturePlayer> opponentBowlers)
        {
            string message;

            List<string> errorMessages = new List<string>();

            foreach (OpponentFixturePlayer bowler in opponentBowlers)
            {
                if (bowler.op_overs == null)
                {
                    message = bowler.op_player_name + " no overs have been entered";
                    errorMessages.Add(message);
                }
                if (bowler.op_overs <= 0)
                {
                    message = bowler.op_player_name + " the number of overs must be greater than 0";
                    errorMessages.Add(message);
                }

                if (bowler.op_maidens > bowler.op_overs)
                {
                    message = bowler.op_player_name + " the number of maidens cannot exceed the numbers of overs";
                    errorMessages.Add(message);
                }

                if (bowler.op_bowling_runs < 0)
                {
                    message = bowler.op_player_name + " runs cannot be less than 0";
                    errorMessages.Add(message);
                }

                if (bowler.op_wickets < 0)
                {
                    message = bowler.op_player_name + " wickets cannot be less than 0";
                    errorMessages.Add(message);
                }
            }
            return errorMessages;
        }

        public double GetTotalBatsmenRuns(List<OpponentFixturePlayer> opponentBatsmen)
        {
            double totalBatsmenRuns = 0;

            foreach (OpponentFixturePlayer batsman in opponentBatsmen)
            {
                if (batsman.op_batting_runs != null)
                {
                    totalBatsmenRuns += (double)batsman.op_batting_runs;
                }
            }

            return totalBatsmenRuns;
        }

        public double GetTotalWicketsLost(List<OpponentFixturePlayer> opponentBatsmen)
        {
            double totalWicketsLost = 0;

            foreach (OpponentFixturePlayer batsman in opponentBatsmen)
            {
                if ((batsman.op_how_out != null) && (batsman.op_how_out != 8) && (batsman.op_how_out != 9))
                {
                    totalWicketsLost += 1;
                }
            }

            return totalWicketsLost;
        }

        public void UpdateOpponentBatsmen(List<OpponentFixturePlayer> opponentBatsmen)
        {
            foreach (OpponentFixturePlayer batsman in opponentBatsmen)
            {
                int fixtureID = batsman.op_fixture_id;
                int batsmanNo = batsman.op_batsman_number;

                OpponentFixturePlayer currentBatsman = new OpponentFixturePlayer()
                {
                    op_fixture_id = fixtureID,
                    op_batsman_number = batsmanNo
                };

                if (batsman.op_player_name != null)
                {
                    currentBatsman.op_player_name = batsman.op_player_name;
                }
                
                if (batsman.op_how_out != null)
                {
                    currentBatsman.op_how_out = batsman.op_how_out;
                }

                if (batsman.op_fielder_name != null)
                {
                    currentBatsman.op_fielder_name = batsman.op_fielder_name;
                }

                if (batsman.op_bowler_name != null)
                {
                    currentBatsman.op_bowler_name = batsman.op_bowler_name;
                }

                if (batsman.op_batting_runs != null)
                {
                    currentBatsman.op_batting_runs = batsman.op_batting_runs;
                }

                db.OpponentFixturePlayers.AddObject(currentBatsman);
                db.SaveChanges();
            }
        }

        public void UpdateOpponentBowlers(List<OpponentFixturePlayer> opponentBowlers)
        {
            foreach (OpponentFixturePlayer bowler in opponentBowlers)
            {
                int fixtureID = bowler.op_fixture_id;
                int batsmanNo = bowler.op_batsman_number;

                OpponentFixturePlayer currentBowler = db.OpponentFixturePlayers.Where(ofp => ofp.op_fixture_id == fixtureID && ofp.op_batsman_number == batsmanNo).Single();

                if (bowler.op_bowler_number != null)
                {
                    currentBowler.op_bowler_number = bowler.op_bowler_number;
                }

                if (bowler.op_overs != null)
                {
                    currentBowler.op_overs = bowler.op_overs;
                }

                if (bowler.op_maidens != null)
                {
                    currentBowler.op_maidens = bowler.op_maidens;
                }

                if (bowler.op_bowling_runs != null)
                {
                    currentBowler.op_bowling_runs = bowler.op_bowling_runs;
                }

                if (bowler.op_wickets != null)
                {
                    currentBowler.op_wickets = bowler.op_wickets;
                }

                db.ObjectStateManager.ChangeObjectState(currentBowler, EntityState.Modified);
                db.SaveChanges();
            }
        }

        public void UpdateOpponentBowlersBowlOnly(List<OpponentFixturePlayer> opponentBowlers)
        {
            foreach (OpponentFixturePlayer bowler in opponentBowlers)
            {
                int fixtureID = bowler.op_fixture_id;
                int batsmanNo = bowler.op_batsman_number;

                OpponentFixturePlayer currentBowler = new OpponentFixturePlayer()
                {
                    op_fixture_id = fixtureID,
                    op_batsman_number = batsmanNo
                };

                if (bowler.op_bowler_number != null)
                {
                    currentBowler.op_bowler_number = bowler.op_bowler_number;
                }

                if (bowler.op_overs != null)
                {
                    currentBowler.op_overs = bowler.op_overs;
                }

                if (bowler.op_maidens != null)
                {
                    currentBowler.op_maidens = bowler.op_maidens;
                }

                if (bowler.op_bowling_runs != null)
                {
                    currentBowler.op_bowling_runs = bowler.op_bowling_runs;
                }

                if (bowler.op_wickets != null)
                {
                    currentBowler.op_wickets = bowler.op_wickets;
                }

                db.OpponentFixturePlayers.AddObject(currentBowler);
                db.SaveChanges();
            }
        }
        

        public void EditOpponentFixtureBatsmen(List<OpponentFixturePlayer> opponentPlayers)
        {
            foreach (OpponentFixturePlayer player in opponentPlayers)
            {
                OpponentFixturePlayer currentPlayer = db.OpponentFixturePlayers.Where(ofp => ofp.op_fixture_id == player.op_fixture_id && ofp.op_batsman_number == player.op_batsman_number).Single();

                currentPlayer.op_player_name = player.op_player_name;
                currentPlayer.op_how_out = player.op_how_out;
                currentPlayer.op_fielder_name = player.op_fielder_name;
                currentPlayer.op_bowler_name = player.op_bowler_name;
                currentPlayer.op_batting_runs = player.op_batting_runs;

                db.ObjectStateManager.ChangeObjectState(currentPlayer, EntityState.Modified);
                db.SaveChanges();
            }
        }

        public void EditOpponentFixtureBowlers(List<OpponentFixturePlayer> opponentPlayers)
        {
            foreach (OpponentFixturePlayer player in opponentPlayers)
            {
                OpponentFixturePlayer currentPlayer = db.OpponentFixturePlayers.Where(ofp => ofp.op_fixture_id == player.op_fixture_id && ofp.op_batsman_number == player.op_batsman_number).Single();

                currentPlayer.op_overs = player.op_overs;
                currentPlayer.op_maidens = player.op_maidens;
                currentPlayer.op_bowling_runs = player.op_bowling_runs;
                currentPlayer.op_wickets = player.op_wickets;

                db.ObjectStateManager.ChangeObjectState(currentPlayer, EntityState.Modified);
                db.SaveChanges();
            }
        }

        public void DeleteOpponentFixturePlayers(int Id)
        {
            List<OpponentFixturePlayer> fixturePlayers = db.OpponentFixturePlayers.Where(ofp => ofp.op_fixture_id == Id).ToList();

            foreach (OpponentFixturePlayer player in fixturePlayers)
            {
                db.OpponentFixturePlayers.DeleteObject(player);
                db.SaveChanges();
            }

        }


    }

    public class OpponentFixturePlayerMetaData
    {
        [Required]
        [Display(Name = "Batsman Number:")]
        [Range(1, 11, ErrorMessage = "Batman number must be in range 1 to 11")]
        public object op_batsman_number;

        [Required(ErrorMessage = "You must enter the player name")]
        [Display(Name = "Name:")]
        public object op_player_name;

        [Required]
        [Display(Name = "How Out:")]
        public object op_how_out;

        [Display(Name = "Fielder:")]
        public object op_fielder_name;

        [Display(Name = "Bowler:")]
        public object op_bowler_name;

        [Display(Name = "Runs:")]
        [Range(0, 300, ErrorMessage = "Runs scored must be greater than or equal to zero")]
        public object op_batting_runs;

        [Display(Name = "Bowler Number:")]
        [Range(1, 11, ErrorMessage = "Batman number must be in range 1 to 11")]
        public object op_bowler_number;

        [Display(Name = "Overs:")]
        [Range(0, 300, ErrorMessage = "Runs scored must be greater than or equal to zero")]
        public object op_overs;

        [Display(Name = "Maidens:")]
        [Range(0, 300, ErrorMessage = "Maidens entered must be greater than or equal to zero")]
        public object op_maidens;

        [Display(Name = "Runs:")]
        [Range(0, 300, ErrorMessage = "Runs entered must be greater than or equal to zero")]
        public object op_bowling_runs;

        [Display(Name = "Wickets:")]
        [Range(0, 10, ErrorMessage = "Wickets taken must be in range 1 to 10")]
        public object op_wickets;

    }

}